let arr = [
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
  [{}, {}, {}, {}, {}, {}, {}, {}, {}],
]
//渲染游戏区域
const renderTable = () => {
  document.querySelector('table').innerHTML = ''
  arr.forEach((item, index) => {
    //第一层遍历创建tr
    let tr = document.createElement('tr')
    tr.dataset.y = index
    item.forEach((item2, index2) => {
      //第二层遍历创建td
      let td = document.createElement('td')
      td.dataset.x = index2
      tr.appendChild(td)
    })
    document.querySelector('table').appendChild(tr)
  })
}
renderTable()
//读取分数
const defen = document.querySelector('.defen')
//声明本次游戏的得分变量
let Defen = 0

//创建构造函数
//第一种类型形状1
function A1(x, y) {
  this.x = x
  this.y = y
  this.shape = function (a) {
    arr[this.y][this.x].num = a
    arr[this.y][this.x - 1].num = a
    arr[this.y][this.x + 1].num = a
    arr[this.y + 1][this.x + 1].num = a
  }
}
//第一种类型形状2
function A2(x, y) {
  this.x = x
  this.y = y
  this.shape = function (a) {
    arr[this.y][this.x + 1].num = a
    arr[this.y - 1][this.x + 1].num = a
    arr[this.y + 1][this.x + 1].num = a
    arr[this.y + 1][this.x].num = a
  }
}
//第一种类型形状3
function A3(x, y) {
  this.x = x
  this.y = y
  this.shape = function (a) {
    arr[this.y + 1][this.x].num = a
    arr[this.y][this.x - 1].num = a
    arr[this.y + 1][this.x + 1].num = a
    arr[this.y + 1][this.x - 1].num = a
  }
}
//第一种类型形状4
function A4(x, y) {
  this.x = x
  this.y = y
  this.shape = function (a) {
    arr[this.y - 1][this.x - 1].num = a
    arr[this.y - 1][this.x].num = a
    arr[this.y][this.x - 1].num = a
    arr[this.y + 1][this.x - 1].num = a
  }
}
//第二种类型，正方形
function B(x, y) {
  this.x = x
  this.y = y
  this.shape = function (a) {
    arr[this.y][this.x].num = a
    arr[this.y][this.x + 1].num = a
    arr[this.y + 1][this.x].num = a
    arr[this.y + 1][this.x + 1].num = a
  }
}

//渲染方块函数
const renderColor = () => {
  arr.forEach((item, index) => {
    const trArr = document.querySelectorAll('tr')
    item.forEach((item2, index2) => {
      //num为1，这个格子渲染黑色
      if (item2.num === 1) {
        trArr[index].querySelectorAll('td')[index2].classList.add('bgc1')
      }
      //num为1，这个格子渲染灰色
      else if (item2.num === 2) {
        trArr[index].querySelectorAll('td')[index2].classList.remove('bgc1')
        trArr[index].querySelectorAll('td')[index2].classList.add('bgc2')
      }
      else {
        trArr[index].querySelectorAll('td')[index2].className = ''
      }
    })
  })
}
//设置原点坐标
let a = new A1(5, 0)
//渲染默认图形
a.shape(1)
renderColor()
//键盘控制事件
document.addEventListener('keydown', function (e) {
  if (flag) {
    if (e.key === 'ArrowDown') {
      down()
    } else if (e.key === 'ArrowRight') {
      right()
    } else if (e.key === 'ArrowLeft') {
      left()
    } else if (e.key === 'ArrowUp') {
      change()
    }
  }
})
//下降函数
const down = () => {
  //清除之前的图形
  a.shape(0)
  a.y += 1
  //渲染移动后的图形
  a.shape(1)
  renderColor()
  //图形到底，渲染成灰色,同时生成新图形
  if (a.y == 10) {
    a.shape(2)
    get()
    nums()
  }
  //判断是否碰到灰色格子，碰到图形就渲染成灰色
  //先把图形的四个格子给找出来
  for (let i = a.y; i < a.y + 2; i++) {
    arr[i].forEach((item, index) => {
      if (item.num == 1) {
        //判断如果这个格子的下面一个格子是灰色
        if (arr[i + 1][index].num == 2) {
          a.shape(2)
          get()
          //判断如果第一排没有灰色格子，才会出来新图形
          if (!arr[0].some(item => item.num == 2)) {
            nums()
          }
        }
      }
    })
  }
  end()
}
//左移动函数
const left = () => {
  //左移动涉及到方块类型和A类型最左边格子的X坐标不同
  //这里用try catch方法来写左移动，报错就说明图形走出界了，执行catch的代码
  try {
    //方块类型，它的X坐标最小值可以为0
    if (a.x > 0) {
      a.shape(0)
      a.x -= 1
      a.shape(1)
      renderColor()
    }
  } catch {
    //A类型的X最小值只能为1
    a.x = 1
    a.shape(1)
    renderColor()
  }
}
//右移动函数
const right = () => {
  try {
    if (a.x < 8) {
      a.shape(0)
      a.x += 1
      a.shape(1)
      renderColor()
    }
  } catch {
    a.x = 7
    a.shape(1)
    renderColor()
  }
}
// 随机图形函数
let num1 = 0
function nums() {
  num1 = Math.floor(Math.random() * 100)
  if (num1 <= 50) {
    //不同类型就生成不同实例
    a = new A1(5, 0)
    a.shape(1)
  } else if (num1 > 50 && num1 <= 100) {
    a = new B(5, 0)
    a.shape(1)
  }
  renderColor()
}
//变形状
const change = () => {
  //先清除当前形状
  a.shape(0)
  //判断这个形状的类型，然后生成新的形状
  if (a.constructor == A1) {
    a = new A2(a.x, a.y)
  } else if (a.constructor == A2) {
    a = new A3(a.x, a.y)
  } else if (a.constructor == A3) {
    a = new A4(a.x, a.y)
  } else {
    a = new A1(a.x, a.y)
  }
  //渲染新形状
  a.shape(1)
  renderColor()
}
//得分函数
function get() {
  //用来计算得分的数组
  let getArr = []
  arr.forEach((item, index) => {
    //筛选颜色为灰色的格子
    const arr0 = item.filter(function (item02) {
      return item02.num == 2
    })
    //如果arr0这个数组长度为9时，说明这一排都是灰色，就清除
    if (arr0.length === 9) {
      //同时将数据放入getArr中，最后会根据数组的长度来判断得分
      getArr.push(arr0)
      for (let i = 0; i < arr0.length; i++) {
        //将这一排的格子num值都清空
        arr0[i].num = 0
      }
      //从下往上遍历,目的是把所有Num为2的格子往下移动一格,遍历选中Num为2的格子，将其清空，然后把其下一排对应的格子赋值
      for (let i = index - 1; i > 0; i--) {
        arr[i].forEach((item, index1) => {
          if (item.num === 2) {
            item.num = 0
            arr[i + 1][index1].num = 2
          }
        })
      }
      renderColor()
    }
  })
  //得分判断
  if (getArr.length == 1) {
    Defen += 1
  } else if (getArr.length == 2) {
    Defen += 4
  } else if (getArr.length == 3) {
    Defen += 10
  } else if (getArr.length == 4) {
    Defen += 20
  }
  //渲染分数
  defen.innerHTML = `得分${Defen}`
}
//定时器
let timer = setInterval(function () {
  down()
}, 500)
//暂停功能
let flag = true
document.addEventListener('keydown', function (e) {
  if (flag) {
    if (e.key === 'Enter') {
      clearInterval(timer)
      flag = !flag
    }
  } else {
    if (e.key === 'Enter') {
      timer = setInterval(function () {
        down()
      }, 500)
      flag = true
    }
  }
})
//游戏结束判定
function end() {
  if (arr[0].some(item => item.num == 2)) {
    clearInterval(timer)
    alert('游戏结束!')
    location.reload()
  }
}